package bosc.cn.service.loan.impl;

import bosc.cn.constant.ApplyConstants;
import bosc.cn.constant.BusinessConstants;
import bosc.cn.dto.common.CommonRequest;
import bosc.cn.dto.common.CommonResponse;
import bosc.cn.dto.common.RequestWrapper;
import bosc.cn.dto.common.ResponseWrapper;
import bosc.cn.service.loan.LoanApprovalService;
import bosc.cn.service.loan.bo.LoanApprovalReqBO;
import bosc.cn.service.loan.bo.LoanApprovalResBO;
import bosc.cn.util.SerialNoGenerator;
import client.SignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import dto.VerifyRequest;
import dto.VerifyResponse;
import lombok.extern.slf4j.Slf4j;
import mapper.*;
import model.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

import static bosc.cn.util.SerialNoGenerator.generateCnsmrSrlNo;

@Slf4j
@Service
public class LoanApprovalServiceImpl implements LoanApprovalService {

    @Autowired
    private WalletInfoMapper walletInfoMapper;

    @Autowired
    private BusinessInfoMapper businessInfoMapper;

    @Autowired
    private WalletUserInfoMapper walletUserInfoMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private SignClient signClient;

    // 银行内部户
    private static final String INTERNAL_WALLET_ID = "BANK_INTERNAL";

    @Override
    public ResponseWrapper<LoanApprovalResBO> approveLoan(LoanApprovalReqBO reqBO) {

        ResponseWrapper<LoanApprovalResBO> resBO = new ResponseWrapper<>();
        CommonResponse head = new CommonResponse();
        LoanApprovalResBO body = new LoanApprovalResBO();


        try {

            // 正常通信
            head.setRetCd("000000");
            head.setRetMsg("通信成功");
            head.setRetTm(LocalDateTime.now());
            // 申请单号不能为空
            if (StringUtils.isBlank(reqBO.getApplyNo())) {
                body.setPrcSts("PR99");
                body.setPrcMsg("申请单号不能为空");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }
            // 查询转入钱包
            LambdaQueryWrapper<WalletInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WalletInfo::getWltId, reqBO.getTfrInWltId());
            WalletInfo walletInfo = walletInfoMapper.selectOne(queryWrapper);
            if (walletInfo == null) {
                body.setPrcSts("PR99");
                body.setPrcMsg("转入钱包不存在");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            LambdaQueryWrapper<WalletInfo> internalWalletQueryWrapper = new LambdaQueryWrapper<>();
            internalWalletQueryWrapper.eq(WalletInfo::getWltId, INTERNAL_WALLET_ID);
            WalletInfo internalWalletInfo = walletInfoMapper.selectOne(internalWalletQueryWrapper);


            // 校验银行内部账户余额是否足够
            if (internalWalletInfo.getWltBal().compareTo(reqBO.getTxnAmt()) < 0) {
                body.setPrcSts("PR88");
                body.setPrcMsg("银行内部账户余额不足");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }


            // userid-walletid 多对多 通过贷款转入钱包ID查找用户ID
            List<String> authList = reqBO.getAuthList();
            LambdaQueryWrapper<WalletUserInfo> userQueryWrapper = new LambdaQueryWrapper<>();
            userQueryWrapper.eq(WalletUserInfo::getWltId, reqBO.getTfrInWltId())
                    .eq(WalletUserInfo::getUserId,authList.get(0));

            WalletUserInfo walletUserInfo0 = walletUserInfoMapper.selectOne(userQueryWrapper);

            if (walletUserInfo0 == null) {
                body.setPrcSts("PR77");
                body.setPrcMsg("领用记录表中转入钱包对应的用户未登记领用:"+authList.get(0));
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }
            userQueryWrapper.clear();
            userQueryWrapper.eq(WalletUserInfo::getWltId, reqBO.getTfrInWltId())
                    .eq(WalletUserInfo::getUserId,authList.get(1));

            WalletUserInfo walletUserInfo1 = walletUserInfoMapper.selectOne(userQueryWrapper);

            if (walletUserInfo1 == null) {
                body.setPrcSts("PR77");
                body.setPrcMsg("领用记录表中转入钱包对应的用户未登记领用:"+authList.get(1));
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            // 全局流水号
            String glblSrlNo = SerialNoGenerator.generateGlblSrlNo("1001"); // 渠道号
            // 构造请求头
            CommonRequest requestHead = new CommonRequest();
            requestHead.setGlblSrlNo(glblSrlNo);   // 透传 bank-service 的全局流水号
            requestHead.setCnsmrSrlNo(generateCnsmrSrlNo("2002"));
            requestHead.setTxnTm(LocalDateTime.now());

            // 封装验签请求
            VerifyRequest verifyRequest = new VerifyRequest();
            verifyRequest.setAuthMsg(reqBO.getAuthMsg());
            verifyRequest.setAuthInfo(reqBO.getAuthInfo());
            verifyRequest.setAuthList(authList);
            verifyRequest.setWltId(reqBO.getTfrInWltId());

            // 调用 sign-service 的 verify 接口
            RequestWrapper<VerifyRequest> wrapper = new RequestWrapper<>();
            wrapper.setHead(requestHead);
            wrapper.setBody(verifyRequest);

            ResponseWrapper<VerifyResponse> verifyResponse = signClient.verify(wrapper);

            // 调用 sign-service 的 verify 接口
//            VerifyResponse verifyResponse = signClient.verify(verifyRequest);
            System.out.println("<<<< 调用 sign-service.verify 返回结果: " + verifyResponse);
            if (!"PR00".equals(verifyResponse.getBody().getPrcSts())) {
                body.setPrcSts(verifyResponse.getBody().getPrcSts());
                body.setPrcMsg("验签失败：" + verifyResponse.getBody().getPrcMsg());
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }


            // 内部账户扣款、转入钱包加款
            internalWalletInfo.setWltBal(internalWalletInfo.getWltBal().subtract(reqBO.getTxnAmt()));
            walletInfo.setWltBal(walletInfo.getWltBal().add(reqBO.getTxnAmt()));

            walletInfo.setOprNm(reqBO.getOprNm());
            walletInfo.setOprIdentTp(reqBO.getOprIdentTp());
            walletInfo.setOprIdentNo(reqBO.getOprIdentNo());
            walletInfo.setOprMblNo(reqBO.getOprTelNo());
            walletInfo.setLastUpdateTime(LocalDateTime.now());
            walletInfo.setLastUpdateOperate("贷款转入钱包收款");

            internalWalletInfo.setOprNm(reqBO.getOprNm());
            internalWalletInfo.setOprIdentTp(reqBO.getOprIdentTp());
            internalWalletInfo.setOprIdentNo(reqBO.getOprIdentNo());
            internalWalletInfo.setOprMblNo(reqBO.getOprTelNo());
            internalWalletInfo.setLastUpdateTime(LocalDateTime.now());
            internalWalletInfo.setLastUpdateOperate("银行内部户向贷款钱包放款");

            walletInfoMapper.updateById(internalWalletInfo);
            walletInfoMapper.updateById(walletInfo);

            // 交易流水表
            BusinessInfo businessInfo = new BusinessInfo();

            // 业务流水号
            String agentSerialNo = UUID.randomUUID().toString().replace("-", "").substring(0, 28);
            businessInfo.setAgentSerialNo(agentSerialNo);
            // 全局流水号、消费方流水号
//            String glblSrlNo = SerialNoGenerator.generateGlblSrlNo("1001"); // 渠道号
            String cnsmrSrlNo = SerialNoGenerator.generateCnsmrSrlNo("2002"); // 系统号
            businessInfo.setGlblSrlNo(glblSrlNo);
            businessInfo.setCnsmrSrlNo(cnsmrSrlNo);
            // 申请单号
            businessInfo.setApplyNo(reqBO.getApplyNo());
            // 转账申请
            businessInfo.setApplyTp(ApplyConstants.ApplyType.LOAN);
            // 申请人工号 上游输入
            businessInfo.setUserId(reqBO.getApplyUserId());
            businessInfo.setTfrOutWltId(internalWalletInfo.getWltId());
            businessInfo.setTfrOutWltNm(internalWalletInfo.getWltName());
            businessInfo.setTfrInWltId(walletInfo.getWltId());
            businessInfo.setTfrInWltNm(walletInfo.getWltName());
            businessInfo.setOprIdentTp(reqBO.getOprIdentTp());
            businessInfo.setOprIdentNo(reqBO.getOprIdentNo());
            businessInfo.setOprNm(reqBO.getOprNm());
            businessInfo.setOprTelNo(reqBO.getOprTelNo());
            businessInfo.setTxnSmy(reqBO.getTxnSmy());
            businessInfo.setTxnAmt(reqBO.getTxnAmt());
            // 转入方手机号为经办人手机号码
            businessInfo.setTfrInTel(reqBO.getOprTelNo());
            businessInfo.setTxnSts(BusinessConstants.TxnStatus.SUCCESS);
            businessInfo.setAuthList(
                    String.join(",", authList)
            );
            businessInfo.setAuthInfo(reqBO.getAuthInfo());
            businessInfo.setAuthMsg(reqBO.getAuthMsg());
            businessInfo.setCreateTime(LocalDateTime.now());
            businessInfo.setLastUpdateTime(LocalDateTime.now());
            businessInfo.setLastUpdateOperate("贷款审批交易成功");
            businessInfoMapper.insert(businessInfo);

            // 返回成功结果
            body.setPrcSts("PR00");
            body.setPrcMsg("贷款发放成功");

        } catch (Exception e) {
            log.error("系统异常：" + e.getMessage(), e);
            // 出现异常，通信失败
            head.setRetCd("999999");
            head.setRetMsg("系统异常：" + e.getMessage());
            head.setRetTm(LocalDateTime.now());
        }

        resBO.setHead(head);
        resBO.setBody(body);
        return resBO;
    }

}
